"""
<Program Name>
  mirrors.py

<Author>
  Konstantin Andrianov.
  Derived from original mirrors.py written by Geremy Condra.

<Started>
  March 12, 2012.

<Copyright>
  See LICENSE for licensing information.

<Purpose>
  Extract a list of mirror urls corresponding to the file type and the location
  of the file with respect to the base url.
"""

# Help with Python 3 compatibility, where the print statement is a function, an
# implicit relative import is invalid, and the '/' operator performs true
# division.  Example:  print 'hello world' raises a 'SyntaxError' exception.
from __future__ import print_function
from __future__ import absolute_import
from __future__ import division
from __future__ import unicode_literals

import os

import tuf
import tuf.util
import tuf.formats

import six

# The type of file to be downloaded from a repository.  The
# 'get_list_of_mirrors' function supports these file types.
# Note hard-coded behavior below.
_SUPPORTED_FILE_TYPES = ['meta', 'target']


def get_list_of_mirrors(file_type, file_path, mirrors_list):
  """
  <Purpose>
    Get a list of mirror urls from a mirrors dictionary, provided the type
    and the path of the file with respect to the base url.

  <Arguments>
    file_type:   <---- NO LONGER OF ANY REAL USE; TODO: REMOVE
      Type of data needed for download, must correspond to one of the strings
      in the list ['meta', 'target'].  'meta' for metadata file type or
      'target' for target file type.  It should correspond to
      NAME_SCHEMA format.

    file_path:
      A relative path to the file that corresponds to RELPATH_SCHEMA format.
      Ex: 'http://url_prefix/targets_path/file_path'

    mirrors_list:
      An object that corresponds to ALT_MIRRORLIST_SCHEMA
      Currently a simple list of URLs.


      OLD:
      # A mirrors_dict object that corresponds to MIRRORDICT_SCHEMA, where
      # keys are strings and values are MIRROR_SCHEMA. An example format
      # of MIRROR_SCHEMA:

      # {'url_prefix': 'http://localhost:8001',
      #  'metadata_path': 'metadata/',
      #  'targets_path': 'targets/',
      #  'confined_target_dirs': ['targets/snapshot1/', ...],
      #  'custom': {...}}

      # The 'custom' field is optional.

  <Exceptions>
    tuf.Error, on unsupported 'file_type'.
    
    tuf.FormatError, on bad argument.

  <Return>
    List of mirror urls corresponding to the file_type and file_path.  If no
    match is found, empty list is returned.
  """

  # Checking if all the arguments have appropriate format.
  tuf.formats.RELPATH_SCHEMA.check_match(file_path)
  tuf.formats.ALT_MIRRORLIST_SCHEMA.check_match(mirrors_list)
  tuf.formats.NAME_SCHEMA.check_match(file_type)

  # Verify 'file_type' is supported.
  if file_type not in _SUPPORTED_FILE_TYPES:
    message = 'Invalid file_type argument.  '+ \
      'Supported file types: '+repr(_SUPPORTED_FILE_TYPES)
    raise tuf.Error(message)

  # No longer supported ):
  # # Reference to 'tuf.util.file_in_confined_directories()' (improve readability).
  # # This function checks whether a mirror should serve a file to the client.
  # # A client may be confined to certain paths on a repository mirror
  # # when fetching target files.  This field may be set by the client when
  # # the repository mirror is added to the 'tuf.client.updater.Updater' object.
  # in_confined_directory = tuf.util.file_in_confined_directories

  list_of_mirrors = []

  for url_prefix in mirrors_list:

    if file_type == 'meta':
      url_prefix += '/metadata'
    else:
      url_prefix += '/targets'

    # for mirror_name, mirror_info in six.iteritems(mirrors_dict):
    #   if file_type == 'meta':
    #     base = mirror_info['url_prefix']+'/'+mirror_info['metadata_path']

    #   # 'file_type' == 'target'.  'file_type' should have been verified to contain
    #   # a supported string value above (either 'meta' or 'target').
    #   else:
    #     targets_path = mirror_info['targets_path']
    #     full_filepath = os.path.join(targets_path, file_path)
    #     if not in_confined_directory(full_filepath,
    #                                  mirror_info['confined_target_dirs']):
    #       continue
    #     base = mirror_info['url_prefix']+'/'+mirror_info['targets_path']

    # urllib.quote(string) replaces special characters in string using the %xx
    # escape.  This is done to avoid parsing issues of the URL on the server
    # side. Do *NOT* pass URLs with Unicode characters without first encoding
    # the URL as UTF-8. We need a long-term solution with #61.
    # http://bugs.python.org/issue1712522
    file_path = six.moves.urllib.parse.quote(file_path)
    url = url_prefix + '/' + file_path.lstrip(os.sep) 
    list_of_mirrors.append(url)

  return list_of_mirrors
